<template>
  <div class="game-container">
    <h1>贪吃蛇游戏</h1>
    <div class="stats">
      <div>分数: {{ score }}</div>
      <div>最高分: {{ highScore }}</div>
      <button @click="startGame" :disabled="isPlaying">
        {{ isPlaying ? '游戏中' : '开始游戏' }}
      </button>
    </div>

    <!-- 游戏区域 -->
    <div class="game-board" :style="{
      width: `${gridSize * cellSize}px`,
      height: `${gridSize * cellSize}px`
    }">
      <!-- 蛇身 -->
      <div
          v-for="(segment, index) in snake"
          :key="index"
          class="snake-segment"
          :style="{
          left: `${segment.x * cellSize}px`,
          top: `${segment.y * cellSize}px`,
          background: index === 0 ? 'darkgreen' : 'green'
        }"
      ></div>

      <!-- 食物 -->
      <div
          v-if="food"
          class="food"
          :style="{
          left: `${food.x * cellSize}px`,
          top: `${food.y * cellSize}px`
        }"
      ></div>

      <!-- 游戏结束提示 -->
      <div v-if="gameOver" class="game-over">
        <h2>游戏结束!</h2>
        <p>最终得分: {{ score }}</p>
        <button @click="startGame">再来一局</button>
      </div>
    </div>

    <div class="controls">
      <p>使用方向键控制蛇的移动</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';

// 游戏配置
const gridSize = 20; // 游戏网格大小
const cellSize = 20; // 每个格子的像素大小
const initialSpeed = 150; // 初始速度(毫秒)

// 游戏状态
const snake = ref([{ x: 10, y: 10 }]); // 蛇的身体，初始位置
const food = ref(null); // 食物位置
const direction = ref({ x: 1, y: 0 }); // 移动方向，初始向右
const nextDirection = ref({ ...direction.value }); // 下一次移动方向
const score = ref(0); // 当前分数
const highScore = ref(0); // 最高分
const isPlaying = ref(false); // 是否正在游戏中
const gameOver = ref(false); // 游戏是否结束
const gameLoop = ref(null); // 游戏循环计时器

// 初始化游戏
const startGame = () => {
  // 重置游戏状态
  snake.value = [{ x: 10, y: 10 }];
  direction.value = { x: 1, y: 0 };
  nextDirection.value = { ...direction.value };
  score.value = 0;
  gameOver.value = false;
  isPlaying.value = true;

  // 生成初始食物
  generateFood();

  // 开始游戏循环
  if (gameLoop.value) clearInterval(gameLoop.value);
  gameLoop.value = setInterval(moveSnake, initialSpeed);
};

// 生成食物
const generateFood = () => {
  // 确保食物不会出现在蛇身上
  let newFood;
  do {
    newFood = {
      x: Math.floor(Math.random() * gridSize),
      y: Math.floor(Math.random() * gridSize)
    };
  } while (snake.value.some(segment => segment.x === newFood.x && segment.y === newFood.y));

  food.value = newFood;
};

// 移动蛇
const moveSnake = () => {
  if (!isPlaying.value) return;

  // 更新方向
  direction.value = { ...nextDirection.value };

  // 创建新头部
  const head = {
    x: snake.value[0].x + direction.value.x,
    y: snake.value[0].y + direction.value.y
  };

  // 检查碰撞
  if (checkCollision(head)) {
    endGame();
    return;
  }

  // 添加新头部
  snake.value.unshift(head);

  // 检查是否吃到食物
  if (head.x === food.value.x && head.y === food.value.y) {
    score.value += 10;
    generateFood();
  } else {
    // 没吃到食物就移除尾部
    snake.value.pop();
  }
};

// 检查碰撞
const checkCollision = (head) => {
  // 撞到墙壁
  if (head.x < 0 || head.x >= gridSize || head.y < 0 || head.y >= gridSize) {
    return true;
  }

  // 撞到自己
  return snake.value.some((segment, index) => {
    return index !== 0 && segment.x === head.x && segment.y === head.y;
  });
};

// 结束游戏
const endGame = () => {
  isPlaying.value = false;
  gameOver.value = true;
  clearInterval(gameLoop.value);

  // 更新最高分
  if (score.value > highScore.value) {
    highScore.value = score.value;
  }
};

// 处理键盘输入
const handleKeydown = (e) => {
  // 只在游戏进行中响应
  if (!isPlaying.value) return;

  // 防止180度转向
  const goingUp = direction.value.y === -1;
  const goingDown = direction.value.y === 1;
  const goingRight = direction.value.x === 1;
  const goingLeft = direction.value.x === -1;

  switch (e.key) {
    case 'ArrowUp':
      if (!goingDown) {
        nextDirection.value = { x: 0, y: -1 };
      }
      break;
    case 'ArrowDown':
      if (!goingUp) {
        nextDirection.value = { x: 0, y: 1 };
      }
      break;
    case 'ArrowLeft':
      if (!goingRight) {
        nextDirection.value = { x: -1, y: 0 };
      }
      break;
    case 'ArrowRight':
      if (!goingLeft) {
        nextDirection.value = { x: 1, y: 0 };
      }
      break;
  }
};

// 监听键盘事件
onMounted(() => {
  window.addEventListener('keydown', handleKeydown);
});

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeydown);
  if (gameLoop.value) clearInterval(gameLoop.value);
});

// 监听游戏状态变化
watch(isPlaying, (newVal) => {
  if (!newVal && gameLoop.value) {
    clearInterval(gameLoop.value);
  }
});
</script>

<style scoped>
.game-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: Arial, sans-serif;
  max-width: 500px;
  margin: 0 auto;
  padding: 20px;
}

.stats {
  display: flex;
  justify-content: space-between;
  width: 100%;
  margin-bottom: 10px;
  font-size: 1.2rem;
}

button {
  padding: 8px 16px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 1rem;
}

button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

.game-board {
  position: relative;
  border: 2px solid #333;
  background-color: #f0f0f0;
}

.snake-segment {
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 3px;
  box-sizing: border-box;
  border: 1px solid #fff;
}

.food {
  position: absolute;
  width: 20px;
  height: 20px;
  background-color: red;
  border-radius: 50%;
  box-sizing: border-box;
  border: 1px solid #000;
}

.game-over {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 20px;
  text-align: center;
  border-radius: 8px;
}

.controls {
  margin-top: 20px;
  font-size: 0.9rem;
  color: #666;
}
</style>
